package com.fandou.airobot.ui.voiceassistant

import android.app.Activity
import android.app.ActivityOptions
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.transition.Transition
import android.transition.TransitionInflater
import android.view.Window
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.blankj.utilcode.util.*
import com.fandou.airobot.R
import com.fandou.airobot.data.bean.NluEntity
import com.fandou.airobot.database.Alarm
import com.fandou.airobot.database.AlarmDatabase
import com.fandou.airobot.service.AlarmReceiver
import com.fandou.airobot.ui.alarm.AlarmActivity
import com.fandou.airobot.ui.recording.AsrExitRecordingEvent
import com.fandou.airobot.ui.recording.RecordCameraActivity
import com.fandou.airobot.ui.recording.RecordingActivity
import com.fandou.airobot.ui.recording.RecordingFragment
import com.fandou.airobot.utils.ChineseNumberSwitcher
import com.fandou.base.view.NumberStepController
import com.google.gson.Gson
import com.jeremyliao.liveeventbus.LiveEventBus
import kotlinx.android.synthetic.main.voice_assistant_activity.*
import java.text.SimpleDateFormat
import java.util.*


/**
 * @author       Jm
 * @date         2020/7/13 9:22
 * @description
 */
class VoiceAssistantActivity : AppCompatActivity() {

    private var mResponseContent: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
        val fade: Transition = TransitionInflater.from(this).inflateTransition(android.R.transition.fade)
        window.enterTransition = fade;//出去的动画
        window.enterTransition = fade;//进来的动画
        BarUtils.transparentStatusBar(this)
        BarUtils.setStatusBarLightMode(this, true)
        getParams()

        setContentView(R.layout.voice_assistant_activity)
        initView()

        updateContentAndSpeak(mResponseContent!!, keepOnAsr = true, needCloseAssistant = false)

        observeClose()
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        getParams()
        LogUtils.d("onNewIntent:${mResponseContent}")

        updateContentAndSpeak(mResponseContent!!, keepOnAsr = true, needCloseAssistant = false)
    }

    private fun getParams() {
        mResponseContent = intent.getStringExtra("content")
    }

    private fun initView() {
        //关闭
        ivCloseVoiceInfo.setOnClickListener {
            stopSpeakAndAsr()
            finishAfterTransition()
        }

        //click 2 识别
        voiceButton.setOnClickListener {
            VibrateUtils.vibrate(100)
            updateContentAndSpeak("", keepOnAsr = true, needCloseAssistant = false)
        }

        observeOnAsrBegin()
        observeOnUpdateVolume()
        observeOnAsrResult()
        observeOnAsrEnd()
        observeOnAsrError()
        observeOnAsrOnLineNluResult()
    }

    /**
     * 订阅开始说话
     */
    private fun observeOnAsrBegin() {
        LiveEventBus
            .get(VoiceAssistantEvent.KEY_ON_ASR_BEGIN, String::class.java)
            .observe(this, Observer {
                startCollectAudio()
            })
    }

    /**
     * 订阅识别结果
     */
    private fun observeOnAsrResult() {
        LiveEventBus
            .get(VoiceAssistantEvent.KEY_ON_ASR_RESULT, String::class.java)
            .observe(this, Observer {
                setMySpeakInfo(it)
            })
    }

    /**
     * 订阅识别说话结束
     */
    private fun observeOnAsrEnd() {
        LiveEventBus
            .get(VoiceAssistantEvent.KEY_ON_ASR_END, String::class.java)
            .observe(this, Observer {
                voiceButton?.updateMicStatus(0)
            })
    }

    /**
     * 订阅识别错误或未处理
     */
    private fun observeOnAsrError() {
        LiveEventBus
            .get(VoiceAssistantEvent.KEY_ON_ASR_ERROR, String::class.java)
            .observe(this, Observer {
                LogUtils.d("onAsrError，语音识别失败或者超时")
                stopSpeakAndAsr()
                finishAfterTransition()
            })
    }

    /**
     * observe麦克风DB音量
     */
    private fun observeOnUpdateVolume() {
        LiveEventBus.get(VoiceAssistantEvent.KEY_ON_UPDATE_VOLUME, Int::class.java)
            .observe(this, Observer {
                voiceButton?.updateMicStatus(it)
            })
    }

    /**
     * 在线语义识别结果
     */
    private fun observeOnAsrOnLineNluResult() {
        LiveEventBus
            .get(VoiceAssistantEvent.KEY_ON_ASR_ONLINE_NLU_RESULT, String::class.java)
            .observe(this, Observer {
                val nluResult = it
                LogUtils.d("onAsrOnlineNluResult:" + nluResult)
                val nlu = Gson().fromJson(nluResult, NluEntity::class.java)
                //if success
                if (nlu.err_no == 0) {
                    //result 不为null 的情况，说明百度识别率额语义词，是含有意图的
                    if (nlu.results != null && nlu.results.size > 0) {
                        processIntent(nlu)
                    }
                    //当result为null，说明没有线上的语义词匹配到
                    else {
                        val keyword = nlu.raw_text;
                        if (keyword.contains("你会做什么") || keyword.contains("你会干什么") || keyword.contains("什么") || keyword.contains("帮助")) {
                            updateContentAndSpeak("您可以说打开记录模式，启动拍照搜题，打开闹钟。也可以说提醒我几点干什么事，多少分钟后提醒我干什么事等等", true, false)
                            return@Observer
                        }

                        //处理 记录模式 下的情况
                        if (keyword.contains("退出记录") || keyword.contains("停止记录")) {
//                            if (ActivityUtils.getTopActivity().componentName.className == CameraActivity::class.java.name) {
                            if (ActivityUtils.isActivityExistsInStack(RecordCameraActivity::class.java)) {
                                LiveEventBus.get(AsrExitRecordingEvent::class.java.name).post(AsrExitRecordingEvent(AsrExitRecordingEvent.EXIT_AND_SAVE_AUTO))
                                updateContentAndSpeak("已退出记录模式", keepOnAsr = false, needCloseAssistant = true)
                            } else {
                                updateContentAndSpeak("您当前没有进行记录！", keepOnAsr = false, needCloseAssistant = true)
                            }
                        }
                        //间隔修改
                        else if (keyword.contains("间隔改为") || keyword.contains("间隔修改为")) {
                            LogUtils.d("截取的keyword：${ChineseNumberSwitcher.getTargetChinese(keyword)}")
                            LogUtils.d("chineseNumber2Int：${ChineseNumberSwitcher.chineseNumber2Int(ChineseNumberSwitcher.getTargetChinese(keyword))}")

                            val targetChinese = ChineseNumberSwitcher.getTargetChinese(keyword)
                            val interval: Int
                            val chineseNumber2Int = ChineseNumberSwitcher.chineseNumber2Int(targetChinese);
                            //-1 说明是正常的数字
                            if (chineseNumber2Int == -1) {
                                interval = targetChinese.toInt()
                            } else {
                                interval = chineseNumber2Int
                            }

                            LogUtils.d("识别到的间隔时间为：${interval}")
                            if (interval < NumberStepController.DEFAULT_MIN_INTERVAL) {
                                updateContentAndSpeak("间隔不能少于${NumberStepController.DEFAULT_MIN_INTERVAL}分钟", keepOnAsr = true, needCloseAssistant = false)
                            } else if (interval > NumberStepController.DEFAULT_MAX_INTERVAL) {
                                updateContentAndSpeak("间隔不能大于${NumberStepController.DEFAULT_MAX_INTERVAL}分钟", keepOnAsr = true, needCloseAssistant = false)
                            } else {
                                LiveEventBus.get(AsrExitRecordingEvent::class.java.name).post(AsrExitRecordingEvent(AsrExitRecordingEvent.MODIFY_INTERVAL, interval))
                                SPUtils.getInstance().put(RecordingFragment.SPKEY_RECORDING_INTERVAL, interval)
                                updateContentAndSpeak("已修改为${interval}分钟")
                            }
                        }
                        //抓拍
                        else if (keyword.contains("抓拍")) {
                            if (ActivityUtils.isActivityExistsInStack(RecordCameraActivity::class.java)) {
                                LiveEventBus.get(AsrExitRecordingEvent::class.java.name).post(AsrExitRecordingEvent(AsrExitRecordingEvent.TAKE_PHOTO))
                                updateContentAndSpeak("好的", keepOnAsr = false, needCloseAssistant = true)
                            }
                        }

                        //处理打开，启动之类的 action
                        else if (keyword.contains("打开") || keyword.contains("启动")) {

                            //拍照搜题
                            if (keyword.contains(resources.getString(R.string.topic_photo_search)) || keyword.contains("搜题")) {
                                LiveEventBus.get(VoiceAssistantEvent.LAUNCHER_TOPIC_SEARCH_ACTIVITY).post("")
                                updateContentAndSpeak("好的", false, true)
                            }
                            //记录模式
                            else if (keyword.contains(resources.getString(R.string.recording_title)) || keyword.contains("记录")) {
                                RecordingActivity.start(this)
                                updateContentAndSpeak("好的", false, true)
                            }
                            //设置闹钟
                            else if (keyword.contains(resources.getString(R.string.alarm_setting)) || keyword.contains("闹钟")) {
                                AlarmActivity.start(this)
                                updateContentAndSpeak("好的", false, true)
                            } else {
                                updateContentAndSpeak(UNKNOWN_LAUNCHER, keepOnAsr = true, needCloseAssistant = false)
                            }

                        }

                        //其他
                        else {
                            mResponseContent = UNKNOWN_VOICE
                            setMySpeakInfo(nlu.raw_text)
                            updateContentAndSpeak(mResponseContent!!, true, needCloseAssistant = false)
                        }
                    }
                }
            })
    }

    private fun processIntent(nlu: NluEntity) {
        val results = nlu.results[0] as NluEntity.Results
        if (results.intent == "SET_REMIND") {
            try {
                //e.g user_remind_time : 17:00:00
                val keyword = nlu.raw_text;
                setMySpeakInfo(keyword)

                var hour: Int = 0
                var minute: Int = 0

                //处理“之后”的闹钟
                if (keyword.contains("之后") || keyword.contains("后")) {
                    //e.g raw_text":"一小时之后提醒我吃饭。"
                    //e.g raw_text":"五分钟之后提醒我去哈皮。"
                    //e.g raw_text":"两小时十分钟之后提醒我吃饭。"
                    if (keyword.contains("小时")) {
                        hour = ChineseNumberSwitcher.chineseNumber2Int(keyword.substring(0, keyword.indexOf("小时")))

                        if (keyword.contains("分钟")) {
                            val substring = keyword.substring(keyword.indexOf("小时") + 2, keyword.indexOf("分钟"));
                            val chineseNumber2Int = ChineseNumberSwitcher.chineseNumber2Int(substring)
                            if (chineseNumber2Int == -1) {
                                minute = substring.toInt()
                            } else {
                                minute = chineseNumber2Int
                            }
                        }
                    } else if (keyword.contains("分钟")) {
                        val substring = keyword.substring(0, keyword.indexOf("分钟"));
                        val chineseNumber2Int = ChineseNumberSwitcher.chineseNumber2Int(substring)
                        if (chineseNumber2Int == -1) {
                            minute = substring.toInt()
                        } else {
                            minute = chineseNumber2Int
                        }
                    }

                    LogUtils.d("time:${hour}:minute:${minute}")
                    var remark = results.slots.user_wild_content[0].word
                    if (remark.isNullOrEmpty()) {
                        remark = ""
                    }

                    val targetAlarmTime = TimeUtils.getNowMills() + 1000 * 60 * 60 * hour + 1000 * 60 * minute
                    LogUtils.d("唤醒时间是：${TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()))}")

                    val alarm: Alarm? = Alarm(
                        targetAlarmTime, remark, TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("HH", Locale.getDefault())).toInt()
                        , TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("mm", Locale.getDefault())).toInt()
                        , false
                    )
                    val rowIdList = AlarmDatabase.getInstance().alarmDao().insertAlarm(alarm) as MutableList<Long>
                    //rowIdList.size大于0代表成功插入数据库，返回了唯一id，需要为这个post出去的实体赋值它的id。
                    if (rowIdList.size != -1) {
                        alarm!!.setId(rowIdList[0])
                        //设置闹钟
                        AlarmReceiver.setReminderAlarm(this, alarm)
                        //通知闹钟列表刷新
                        LiveEventBus.get(Alarm::class.java.name).post(alarm)
                        updateContentAndSpeak("好的", keepOnAsr = false, needCloseAssistant = true)
                    }
                } else {
                    //      如果成功识别，norm就是一个时间。08:00:00"或者2020-07-16|08:00:00
                    val currentTime = results.slots?.user_remind_time!![0].norm
                    val targetAlarmTime: Long
                    val isRepeat: Boolean
                    //如果有|，则是这样的格式2020-07-14|18:00:00
                    if (currentTime.contains("|")) {
                        isRepeat = false
                        targetAlarmTime = TimeUtils.string2Millis(currentTime, SimpleDateFormat("yyyy-MM-dd|HH:mm:ss", Locale.getDefault()))
                        hour = TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("HH", Locale.getDefault())).toInt()
                        minute = TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("mm", Locale.getDefault())).toInt()
                        LogUtils.d("识别到的时间是—:${targetAlarmTime}，hour:${hour},minute:${minute}")
                    }

                    //如果有|,是这样的格式08:00:00
                    else {
                        isRepeat = true
                        hour = currentTime.subSequence(0, 2).toString().toInt()
                        minute = currentTime.subSequence(3, 5).toString().toInt()
                        val time = Calendar.getInstance()
                        time[Calendar.HOUR_OF_DAY] = hour
                        time[Calendar.MINUTE] = minute

                        targetAlarmTime = time.timeInMillis
                    }

                    LogUtils.d("设置闹钟——alarmTime:${targetAlarmTime},日期是：${TimeUtils.millis2String(targetAlarmTime, SimpleDateFormat("yyyy-MM-dd|HH:mm:ss"))}")
                    LogUtils.d("设置闹钟——hour:$hour")
                    LogUtils.d("设置闹钟——minute:$minute")


                    var remark = results.slots.user_wild_content[0].word
                    if (remark.isNullOrEmpty()) {
                        remark = ""
                    }

                    val alarm: Alarm? = Alarm(targetAlarmTime, remark, hour, minute, isRepeat)
                    val rowIdList = AlarmDatabase.getInstance().alarmDao().insertAlarm(alarm) as MutableList<Long>
                    //rowIdList.size大于0代表成功插入数据库，返回了唯一id，需要为这个post出去的实体赋值它的id。
                    if (rowIdList.size != -1) {
                        alarm!!.setId(rowIdList[0])
                        //设置闹钟
                        AlarmReceiver.setReminderAlarm(this, alarm)
                        //通知闹钟列表刷新
                        LiveEventBus.get(Alarm::class.java.name).post(alarm)

                        updateContentAndSpeak("好的", keepOnAsr = false, needCloseAssistant = true)
                    }
                }


            } catch (e: Exception) {
                e.printStackTrace()
                updateContentAndSpeak(UNKNOWN_VOICE, keepOnAsr = true, needCloseAssistant = false)
            }
        } else {
            mResponseContent = UNKNOWN_VOICE
            updateContentAndSpeak(mResponseContent!!)
        }
    }


    /**
     * 更新说话的内容
     * @param keepOnAsr 是否继续需要发起语音识别，当为false的情况下，需要手动点击按钮发起语音识别
     */
    private fun updateContentAndSpeak(respondContent: String, keepOnAsr: Boolean = true, needCloseAssistant: Boolean = true) {
        this.mResponseContent = respondContent
        setVoiceAssistantSpeakInfo(mResponseContent)
        LiveEventBus.get(VoiceAssistantEvent.KEY_START_ASR).post(VoiceAssistantEvent(mResponseContent, keepOnAsr, needCloseAssistant))
    }

    /**
     * 订阅关闭事件
     * 用于通知给AiRobot阅读后的回调
     */
    private fun observeClose() {
        LiveEventBus.get(VoiceAssistantEvent.CLOSE_VOICE_ASSISTANT, String::class.java)
            .observe(this, Observer {
                finishAfterTransition()
            })
    }

    /**
     * 开始收集声音
     */
    private fun startCollectAudio() {
//        voiceButton.startCollectVoice()
    }

    /**
     * 设置语音助手当前说的内容
     */
    private fun setVoiceAssistantSpeakInfo(content: String?) {
        content?.let {
            tvVoiceAssistant?.text = content
        }
    }

    /**
     * 设置当前用户说的内容
     */
    private fun setMySpeakInfo(content: String?) {
        content?.let {
            tvSpeakInfo.text = content
        }
    }

    override fun onDestroy() {
        stopSpeakAndAsr()
        super.onDestroy()
    }

    private fun stopSpeakAndAsr() {
        LiveEventBus.get(VoiceAssistantEvent.STOP_SPEAK_AND_ASR).post("")
    }


    companion object {

        /**
         * 当前这个activity的关闭延迟时间。
         * 不能太短不能太长。太短会导致AiRobotActivity还未能接收到事件就被停止了。
         */
        const val DESTROY_DELAY_TIME = 800L

        const val UNKNOWN_VOICE = "对不起，没听懂你说什么，请再说一遍…";

        const val UNKNOWN_LAUNCHER = "对不起，找不到你说的功能，请再说一遍…";

        const val SAY_HELLO = "请问需要什么帮助吗？我正在听…";

        @JvmStatic
        fun start(context: Context, content: String?) {
            val intent = Intent(context, VoiceAssistantActivity::class.java)
            intent.putExtra("content", content)
            context.startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(context as Activity).toBundle());
        }
    }

}